home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / PPPLCP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-30  |  26.9 KB  |  1,042 lines

  1. /*
  2.  *  PPPLCP.C    -- negotiate data link options
  3.  *
  4.  *    This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  *    Jan 91    Bill_Simpson@um.cc.umich.edu
  7.  *        Computer Systems Consulting Services
  8.  *
  9.  *    Acknowledgements and correction history may be found in PPP.C
  10.  */
  11.  
  12. #include "global.h"
  13. #ifdef PPP
  14. #include "mbuf.h"
  15. #include "iface.h"
  16. #include "ppp.h"
  17. #include "pppfsm.h"
  18. #include "ppplcp.h"
  19. #include "ppppap.h"
  20. #include "cmdparse.h"
  21. #include "devparam.h"
  22. #include "trace.h"
  23.  
  24.  
  25. #if !defined(_lint)
  26. static char rcsid[] OPTIONAL = "$Id: ppplcp.c,v 1.14 1997/07/31 00:44:20 root Exp root $";
  27. #endif
  28.  
  29. /* These defaults are defined in the PPP RFCs, and must not be changed */
  30. static struct lcp_value_s lcp_default =
  31. {
  32.     FALSE,            /* no need to negotiate defaults */
  33.  
  34.     LCP_MRU_DEFAULT,
  35.     (uint32) LCP_ACCM_DEFAULT,
  36.     0,            /* no authentication */
  37.     0L,            /* no magic number */
  38. #if 0
  39.     0,            /* no encryption */
  40.     0L,            /* no reporting period */
  41. #endif
  42. };
  43.  
  44.  
  45. /* for test purposes, accept anything we understand in the NAK */
  46. static int16 lcp_negotiate = LCP_N_MRU | LCP_N_ACCM | LCP_N_AUTHENT
  47.     | LCP_N_PFC | LCP_N_ACFC | LCP_N_MAGIC;
  48.  
  49. static byte_t option_length[] =
  50. {
  51.     0,            /* unused */
  52.     4,            /* MRU */
  53.     6,            /* ACCM */
  54.     4,            /* authentication */
  55.     4,            /* encryption */
  56.     6,            /* magic number */
  57.     6,            /* monitor reporting period */
  58.     2,            /* Protocol compression */
  59.     2            /* Address/Control compression */
  60. };
  61.  
  62.  
  63. static int dolcp_local (int argc, char *argv[], void *p);
  64. static int dolcp_open (int argc, char *argv[], void *p);
  65. static int dolcp_remote (int argc, char *argv[], void *p);
  66.  
  67. static int dolcp_accm (int argc, char *argv[], void *p);
  68. static int dolcp_acfc (int argc, char *argv[], void *p);
  69. static int dolcp_auth (int argc, char *argv[], void *p);
  70. static int dolcp_magic (int argc, char *argv[], void *p);
  71. static int dolcp_mru (int argc, char *argv[], void *p);
  72. static int dolcp_pfc (int argc, char *argv[], void *p);
  73. static int dolcp_default (int argc, char *argv[], void *p);
  74.  
  75. static void lcp_option (struct mbuf ** bpp, struct lcp_value_s * value_p,
  76.     byte_t o_type, byte_t o_length,    struct mbuf ** copy_bpp);
  77. static void lcp_makeoptions (struct mbuf ** bpp, struct lcp_value_s * value_p, int16 negotiating);
  78. static struct mbuf *lcp_makereq (struct fsm_s * fsm_p);
  79.  
  80. static int lcp_check (struct mbuf ** bpp, struct lcp_s * lcp_p,
  81.       struct lcp_side_s * side_p, struct option_hdr * option_p, int request);
  82.  
  83. static int lcp_request (struct fsm_s * fsm_p, struct config_hdr * config, struct mbuf * data);
  84. static int lcp_ack (struct fsm_s * fsm_p, struct config_hdr * ackcnf, struct mbuf * data);
  85. static int lcp_nak (struct fsm_s * fsm_p, struct config_hdr * nakcnf, struct mbuf * data);
  86. static int lcp_reject (struct fsm_s * fsm_p, struct config_hdr * rejcnf, struct mbuf * data);
  87.  
  88. static void lcp_reset (struct fsm_s * fsm_p);
  89. static void lcp_starting (struct fsm_s * fsm_p);
  90. static void lcp_stopping (struct fsm_s * fsm_p);
  91.  
  92. static void lcp_closing (struct fsm_s * fsm_p);
  93. static void lcp_opening (struct fsm_s * fsm_p);
  94.  
  95. static void lcp_free (struct fsm_s * fsm_p);
  96.  
  97.  
  98. static struct fsm_constant_s lcp_constants =
  99. {
  100.     "Lcp",
  101.     PPP_LCP_PROTOCOL,
  102.     0x0FFE,            /* codes 1-11 recognized */
  103.  
  104.     Lcp,
  105.     LCP_REQ_TRY,
  106.     LCP_NAK_TRY,
  107.     LCP_TERM_TRY,
  108.     LCP_TIMEOUT * 1000L,
  109.  
  110.     lcp_free,
  111.  
  112.     lcp_reset,
  113.     lcp_starting,
  114.     lcp_opening,
  115.     lcp_closing,
  116.     lcp_stopping,
  117.  
  118.     lcp_makereq,
  119.     lcp_request,
  120.     lcp_ack,
  121.     lcp_nak,
  122.     lcp_reject
  123. };
  124.  
  125.  
  126. /************************************************************************/
  127.  
  128. /* "ppp <iface> lcp" subcommands */
  129. static struct cmds Lcpcmds[] =
  130. {
  131.     { "close",    doppp_close,    0, 0, NULLCHAR },
  132.     { "listen",    doppp_passive,    0, 0, NULLCHAR },
  133.     { "local",    dolcp_local,    0, 0, NULLCHAR },
  134.     { "open",    dolcp_open,    0, 0, NULLCHAR },
  135.     { "remote",    dolcp_remote,    0, 0, NULLCHAR },
  136.     { "timeout",    doppp_timeout,    0, 0, NULLCHAR },
  137.     { "try",    doppp_try,    0, 0, NULLCHAR },
  138.     { NULLCHAR,    0,        0, 0, NULLCHAR }
  139. };
  140.  
  141.  
  142. /* { "ppp <iface> lcp [local | remote]" subcommands */
  143. static struct cmds Lcpside_cmds[] =
  144. {
  145.     { "accm",        dolcp_accm,    0, 0, NULLCHAR },
  146.     { "acfc",        dolcp_acfc,    0, 0, NULLCHAR },
  147.     { "authenticate",    dolcp_auth,    0, 0, NULLCHAR },
  148.     { "magic",        dolcp_magic,    0, 0, NULLCHAR },
  149.     { "mru",        dolcp_mru,    0, 0, NULLCHAR },
  150.     { "pfc",        dolcp_pfc,    0, 0, NULLCHAR },
  151.     { "default",        dolcp_default,    0, 0, NULLCHAR },
  152.     { NULLCHAR,        0,        0, 0, NULLCHAR }
  153. };
  154.  
  155.  
  156.  
  157. int
  158. doppp_lcp (int argc, char *argv[], void *p)
  159. {
  160. register struct iface *ifp = p;
  161. register struct ppp_s *ppp_p = ifp->edv;
  162.  
  163.     return subcmd (Lcpcmds, argc, argv, &(ppp_p->fsm[Lcp]));
  164. }
  165.  
  166.  
  167.  
  168. static int
  169. dolcp_local (int argc, char *argv[], void *p)
  170. {
  171. struct fsm_s *fsm_p = p;
  172. struct lcp_s *lcp_p = fsm_p->pdv;
  173.  
  174.     return subcmd (Lcpside_cmds, argc, argv, &(lcp_p->local));
  175. }
  176.  
  177.  
  178.  
  179. static int
  180. dolcp_open (int argc, char *argv[], void *p)
  181. {
  182. struct fsm_s *fsm_p = p;
  183.  
  184.     (void) doppp_active (argc, argv, p);
  185.  
  186.     if (fsm_p->ppp_p->phase >= pppLCP)
  187.         fsm_start (fsm_p);
  188.  
  189.     return 0;
  190. }
  191.  
  192.  
  193.  
  194. static int
  195. dolcp_remote (int argc, char *argv[], void *p)
  196. {
  197. struct fsm_s *fsm_p = p;
  198. struct lcp_s *lcp_p = fsm_p->pdv;
  199.  
  200.     return subcmd (Lcpside_cmds, argc, argv, &(lcp_p->remote));
  201. }
  202.  
  203.  
  204.  
  205. /************************************************************************/
  206.  
  207. static int
  208. dolcp_accm (int argc, char *argv[], void *p)
  209. {
  210. struct lcp_side_s *side_p = p;
  211.  
  212.     if (argc < 2)
  213.         tprintf ("0x%08lx\n", side_p->want.accm);
  214.     else if (stricmp (argv[1], "allow") == 0)
  215.         return bit16cmd (&(side_p->will_negotiate), LCP_N_ACCM, "Allow ACCM", --argc, &argv[1]);
  216.     else {
  217.         side_p->want.accm = strtoul (argv[1], NULLCHARP, 0);
  218.         if (side_p->want.accm != LCP_ACCM_DEFAULT)
  219.             side_p->want.negotiate |= LCP_N_ACCM;
  220.         else
  221.             side_p->want.negotiate &= ~LCP_N_ACCM;
  222.     }
  223.     return 0;
  224. }
  225.  
  226.  
  227.  
  228. static int
  229. dolcp_acfc (int argc, char *argv[], void *p)
  230. {
  231. struct lcp_side_s *side_p = p;
  232.  
  233.     if (stricmp (argv[1], "allow") == 0)
  234.         return bit16cmd (&(side_p->will_negotiate), LCP_N_ACFC,
  235.             "Allow Address/Control Field Compression", --argc, &argv[1]);
  236.  
  237.     return bit16cmd (&(side_p->want.negotiate), LCP_N_ACFC,
  238.          "Address/Control Field Compression", argc, argv);
  239. }
  240.  
  241.  
  242.  
  243. static int
  244. dolcp_auth (int argc, char *argv[], void *p)
  245. {
  246. struct lcp_side_s *side_p = p;
  247.  
  248.     if (argc < 2) {
  249.         if (side_p->want.negotiate & LCP_N_AUTHENT) {
  250.             switch (side_p->want.authentication) {
  251.                 case PPP_PAP_PROTOCOL:
  252.                     tputs ("Pap\n");
  253.                     break;
  254.                 default:
  255.                     tprintf ("0x%04x\n", side_p->want.authentication);
  256.                     break;
  257.             }
  258.         } else
  259.             tputs ("None\n");
  260.     } else if (stricmp (argv[1], "allow") == 0)
  261.         return bit16cmd (&(side_p->will_negotiate), LCP_N_AUTHENT, "Allow Authentication", --argc, &argv[1]);
  262.     else if (stricmp (argv[1], "pap") == 0) {
  263.         side_p->want.negotiate |= LCP_N_AUTHENT;
  264.         side_p->want.authentication = PPP_PAP_PROTOCOL;
  265.     } else if (stricmp (argv[1], "none") == 0)
  266.         side_p->want.negotiate &= ~LCP_N_AUTHENT;
  267.     else {
  268.         tputs ("allow pap none\n");
  269.         return 1;
  270.     }
  271.     return 0;
  272. }
  273.  
  274.  
  275.  
  276. static int
  277. dolcp_magic (int argc, char *argv[], void *p)
  278. {
  279. struct lcp_side_s *side_p = p;
  280. int result = 0;
  281. int32 theclock;
  282.  
  283.     if (argc < 2)
  284.         tprintf ("%ld\n", side_p->want.magic_number);
  285.     else if (stricmp (argv[1], "allow") == 0)
  286.         return bit16cmd (&(side_p->will_negotiate), LCP_N_MAGIC,
  287.             "Allow Magic Number", --argc, &argv[1]);
  288.     else {
  289.         register uint32 x = strtoul (argv[1], NULLCHARP, 0);
  290.  
  291.         if (!x) {
  292.             int test;
  293.  
  294.             /* Check for keyword */
  295.             result = setbool (&test, "Magic Number", argc, argv);
  296.  
  297.             if (test)     {    /* Make a non-zero random number */
  298.                 theclock = rdclock();
  299.                 x = theclock << ((theclock & 0xf) + 8);    /*lint !e703 !e564 */
  300.             }
  301.         }
  302.         if (x)
  303.             side_p->want.negotiate |= LCP_N_MAGIC;
  304.         else
  305.             side_p->want.negotiate &= ~LCP_N_MAGIC;
  306.  
  307.         side_p->want.magic_number = x;
  308.     }
  309.     return result;
  310. }
  311.  
  312.  
  313.  
  314. static int
  315. dolcp_mru (int argc, char *argv[], void *p)
  316. {
  317. struct lcp_side_s *side_p = p;
  318.  
  319.     if (argc < 2)
  320.         tprintf ("%d\n", side_p->want.mru);
  321.     else if (stricmp (argv[1], "allow") == 0)
  322.         return bit16cmd (&(side_p->will_negotiate), LCP_N_MRU,
  323.             "Allow MRU", --argc, &argv[1]);
  324.     else {
  325.         register int x = (int) strtol (argv[1], NULLCHARP, 0);
  326.  
  327.         if (x < LCP_MRU_LO || x > LCP_MRU_HI) {
  328.             tprintf ("MRU %s (%d) out of range %d thru %d\n",
  329.                  argv[1], x, LCP_MRU_LO, LCP_MRU_HI);
  330.             return -1;
  331.         } else if (x != LCP_MRU_DEFAULT)
  332.             side_p->want.negotiate |= LCP_N_MRU;
  333.         else
  334.             side_p->want.negotiate &= ~LCP_N_MRU;
  335.  
  336.         side_p->want.mru = (int16) x;
  337.     }
  338.     return 0;
  339. }
  340.  
  341.  
  342.  
  343. static int
  344. dolcp_pfc (int argc, char *argv[], void *p)
  345. {
  346. struct lcp_side_s *side_p = p;
  347.  
  348.     if (stricmp (argv[1], "allow") == 0)
  349.         return bit16cmd (&(side_p->will_negotiate), LCP_N_PFC,
  350.             "Allow Protocol Field Compression", --argc, &argv[1]);
  351.  
  352.     return bit16cmd (&(side_p->want.negotiate), LCP_N_PFC,
  353.              "Protocol Field Compression", argc, argv);
  354. }
  355.  
  356.  
  357.  
  358. static int
  359. dolcp_default (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  360. {
  361. struct lcp_side_s *side_p = p;
  362.  
  363.     ASSIGN (side_p->want, lcp_default);
  364.     return 0;
  365. }
  366.  
  367.  
  368.  
  369. /************************************************************************/
  370. /*            E V E N T   P R O C E S S I N G            */
  371. /************************************************************************/
  372.  
  373. static void
  374. lcp_option (
  375. struct mbuf **bpp,
  376. struct lcp_value_s *value_p,
  377. byte_t o_type,
  378. byte_t o_length,
  379. struct mbuf **copy_bpp
  380. ) {
  381. struct mbuf *bp;
  382. register unsigned char *cp;
  383. register int toss = o_length - OPTION_HDR_LEN;
  384.  
  385.     if ((bp = alloc_mbuf (o_length)) == NULLBUF)
  386.         return;
  387.  
  388.     cp = bp->data;
  389.     *cp++ = o_type;
  390.     *cp++ = o_length;
  391.  
  392.     switch (o_type) {
  393.         case LCP_MRU:
  394.             cp = put16 (cp, value_p->mru);
  395.             toss -= 2;
  396. #ifdef PPP_DEBUG_OPTIONS
  397.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  398.                 trace_log (PPPiface, "    making MRU: %d", value_p->mru);
  399. #endif
  400.             break;
  401.  
  402.         case LCP_ACCM:
  403.             cp = put32 (cp, (unsigned long) value_p->accm);
  404.             toss -= 4;
  405. #ifdef PPP_DEBUG_OPTIONS
  406.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  407.                 trace_log (PPPiface, "    making ACCM: 0x%08lx", value_p->accm);
  408. #endif
  409.             break;
  410.  
  411.         case LCP_AUTHENT:
  412.             cp = put16 (cp, value_p->authentication);
  413.             toss -= 2;
  414. #ifdef PPP_DEBUG_OPTIONS
  415.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  416.                 trace_log (PPPiface, "    making Auth Protocol: 0x%04x",
  417.                        value_p->authentication);
  418. #endif
  419.             break;
  420.  
  421.         case LCP_MAGIC:
  422.             cp = put32 (cp, (unsigned long) value_p->magic_number);
  423.             toss -= 4;
  424. #ifdef PPP_DEBUG_OPTIONS
  425.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  426.                 trace_log (PPPiface, "    making Magic Number: 0x%08lx",
  427.                        value_p->magic_number);
  428. #endif
  429.             break;
  430.  
  431.         case LCP_PFC:
  432. #ifdef PPP_DEBUG_OPTIONS
  433.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  434.                 trace_log (PPPiface, "    making Protocol compression");
  435. #endif
  436.             break;
  437.  
  438.         case LCP_ACFC:
  439. #ifdef PPP_DEBUG_OPTIONS
  440.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  441.                 trace_log (PPPiface, "    making Addr/Ctl compression");
  442. #endif
  443.             break;
  444.  
  445.         case LCP_ENCRYPT:    /* not implemented */
  446.         case LCP_QUALITY:    /* not implemented */
  447.         default:
  448. #ifdef PPP_DEBUG_OPTIONS
  449.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  450.                 trace_log (PPPiface, "    making unimplemented type %d", o_type);
  451. #endif
  452.             break;
  453.     }
  454.  
  455.     while (toss-- > 0)
  456.         *cp++ = uchar(pullchar (copy_bpp));
  457.  
  458.     bp->cnt += o_length;
  459.     append (bpp, bp);
  460. }
  461.  
  462.  
  463.  
  464. /************************************************************************/
  465. /* Build a list of options */
  466. static void
  467. lcp_makeoptions (struct mbuf **bpp, struct lcp_value_s *value_p, int16 negotiating)
  468. {
  469. register int o_type;
  470.  
  471.     PPP_DEBUG_ROUTINES ("lcp_makeoptions()");
  472.  
  473.     for (o_type = 1; o_type <= LCP_OPTION_LIMIT; o_type++) {
  474.         if (negotiating & (1 << o_type))
  475.             lcp_option (bpp, value_p, uchar(o_type), option_length[o_type], NULLBUFP);
  476.     }
  477. }
  478.  
  479.  
  480.  
  481. /************************************************************************/
  482. /* Build a request to send to remote host */
  483. static struct mbuf *
  484. lcp_makereq (struct fsm_s *fsm_p)
  485. {
  486. struct lcp_s *lcp_p = fsm_p->pdv;
  487. struct mbuf *req_bp = NULLBUF;
  488.  
  489.     PPP_DEBUG_ROUTINES ("lcp_makereq()");
  490.  
  491.     lcp_makeoptions (&req_bp, &(lcp_p->local.work), lcp_p->local.work.negotiate);
  492.     return (req_bp);
  493. }
  494.  
  495.  
  496.  
  497. /************************************************************************/
  498. /* Check the options, updating the working values.
  499.  * Returns -1 if ran out of data, ACK/NAK/REJ as appropriate.
  500.  */
  501. static int
  502. lcp_check (
  503. struct mbuf **bpp,
  504. struct lcp_s *lcp_p,
  505. struct lcp_side_s *side_p,
  506. struct option_hdr *option_p,
  507. int request
  508. ) {
  509. int toss = option_p->len - OPTION_HDR_LEN;
  510. int option_result = CONFIG_ACK;    /* Assume good values */
  511.  
  512.     switch (option_p->type) {
  513.         case LCP_MRU:
  514.             side_p->work.mru = pull16 (bpp);
  515.             toss -= 2;
  516. #ifdef PPP_DEBUG_OPTIONS
  517.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  518.                 trace_log (PPPiface, "    checking MRU: %d", side_p->work.mru);
  519. #endif
  520.             /* Check if new value is appropriate */
  521.             if (side_p->work.mru < LCP_MRU_LO) {
  522.                 side_p->work.mru = LCP_MRU_LO;
  523.                 option_result = CONFIG_NAK;
  524.             } else if (side_p->work.mru > LCP_MRU_HI) {
  525.                 side_p->work.mru = LCP_MRU_HI;
  526.                 option_result = CONFIG_NAK;
  527.             }
  528.             if (request && (side_p->want.negotiate & LCP_N_MRU)
  529.                 && side_p->work.mru > side_p->want.mru) {
  530.                 side_p->work.mru = side_p->want.mru;
  531.                 option_result = side_p->want.mru;
  532.             }
  533.             break;
  534.  
  535.         case LCP_ACCM:
  536.             side_p->work.accm = pull32 (bpp);
  537.             toss -= 4;
  538. #ifdef PPP_DEBUG_OPTIONS
  539.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  540.                 trace_log (PPPiface, "    checking ACCM: 0x%08lx", side_p->work.accm);
  541. #endif
  542.             /* Remote host may ask to escape more control  */
  543.             /* characters than we require, but must escape */
  544.             /* at least the control chars that we require. */
  545.             if ((!request || (side_p->want.negotiate & LCP_N_ACCM))
  546.                 && side_p->work.accm !=
  547.                 (side_p->work.accm | side_p->want.accm)) {
  548.                 side_p->work.accm |= side_p->want.accm;
  549.                 option_result = CONFIG_NAK;
  550.             }
  551.             break;
  552.  
  553.         case LCP_AUTHENT:
  554.             side_p->work.authentication = pull16 (bpp);
  555.             toss -= 2;
  556. #ifdef PPP_DEBUG_OPTIONS
  557.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  558.                 trace_log (PPPiface, "    checking Auth Protocol: 0x%04x",
  559.                        side_p->work.authentication);
  560. #endif
  561.             /* Check if new value is appropriate */
  562.             switch (side_p->work.authentication) {
  563.                 case PPP_PAP_PROTOCOL:
  564.                     /* Yes */
  565.                     break;
  566.                 default:
  567.                     side_p->work.authentication = PPP_PAP_PROTOCOL;
  568.                     option_result = CONFIG_NAK;
  569.                     break;
  570.             };
  571.             break;
  572.  
  573.         case LCP_MAGIC:
  574.             side_p->work.magic_number = pull32 (bpp);
  575.             toss -= 4;
  576. #ifdef PPP_DEBUG_OPTIONS
  577.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  578.                 trace_log (PPPiface, "    checking Magic Number: 0x%08lx",
  579.                        side_p->work.magic_number);
  580. #endif
  581.  
  582.             /* Ensure that magic numbers are different */
  583.             if (side_p->work.magic_number == 0L
  584.                 || lcp_p->remote.work.magic_number == lcp_p->local.work.magic_number) {
  585.                 side_p->work.magic_number += (uint32) rdclock();
  586.                 option_result = CONFIG_NAK;
  587.             }
  588.             break;
  589.  
  590.         case LCP_PFC:
  591. #ifdef PPP_DEBUG_OPTIONS
  592.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  593.                 trace_log (PPPiface, "    checking Protocol compression");
  594. #endif
  595.             break;
  596.  
  597.         case LCP_ACFC:
  598. #ifdef PPP_DEBUG_OPTIONS
  599.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  600.                 trace_log (PPPiface, "    checking Addr/Ctl compression");
  601. #endif
  602.             break;
  603.  
  604.         case LCP_ENCRYPT:    /* not implemented */
  605.         case LCP_QUALITY:    /* not implemented */
  606.         default:
  607.             option_result = CONFIG_REJ;
  608.             break;
  609.     }
  610.  
  611.     if (option_p->type > LCP_OPTION_LIMIT || !(side_p->will_negotiate & (1 << option_p->type)))
  612.         option_result = CONFIG_REJ;
  613.  
  614.     if (toss < 0)
  615.         return -1;
  616.  
  617.     if (!request && toss > 0) {
  618.         /* toss extra bytes in option */
  619.         while (toss-- > 0) {
  620.             if (pullchar (bpp) == -1)
  621.                 return -1;
  622.         }
  623.     }
  624.     return (option_result);
  625. }
  626.  
  627.  
  628.  
  629. /************************************************************************/
  630. /* Check Link Control options requested by the remote host */
  631. static int
  632. lcp_request (struct fsm_s *fsm_p, struct config_hdr *config, struct mbuf *data)
  633. {
  634. struct lcp_s *lcp_p = fsm_p->pdv;
  635. int32 signed_length = config->len;
  636. struct mbuf *reply_bp = NULLBUF;    /* reply packet */
  637. int reply_result = CONFIG_ACK;    /* reply to request */
  638. int16 desired;        /* desired to negotiate */
  639. struct option_hdr option;    /* option header storage */
  640. int option_result;    /* option reply */
  641.  
  642.     PPP_DEBUG_ROUTINES ("lcp_request()");
  643.     lcp_p->remote.work.negotiate = FALSE;    /* clear flags */
  644.  
  645.     /* Process options requested by remote host */
  646.     while (signed_length > 0 && ntohopt (&option, &data) != -1) {
  647.         if ((signed_length -= option.len) < 0) {
  648.             PPP_DEBUG_CHECKS ("LCP REQ: bad header length");
  649.             free_p (data);
  650.             free_p (reply_bp);
  651.             return -1;
  652.         }
  653.         if ((option_result = lcp_check (&data, lcp_p, &(lcp_p->remote), &option, TRUE)) == -1) {
  654.             PPP_DEBUG_CHECKS ("LCP REQ: ran out of data");
  655.             free_p (data);
  656.             free_p (reply_bp);
  657.             return -1;
  658.         }
  659. #ifdef PPP_DEBUG_OPTIONS
  660.         if (PPPtrace & PPP_DEBUG_OPTIONS)
  661.             trace_log (PPPiface, "LCP REQ: result %s, option %d, length %d",
  662.                 fsmCodes[option_result], option.type, option.len);
  663. #endif
  664.         if (option_result < reply_result)
  665.             continue;
  666.         else if (option_result > reply_result) {
  667.             /* Discard current list of replies */
  668.             free_p (reply_bp);
  669.             reply_bp = NULLBUF;
  670.             reply_result = option_result;
  671.         }
  672.         /* remember that we processed option */
  673.         if (option_result != CONFIG_REJ && option.type <= LCP_OPTION_LIMIT)
  674.             lcp_p->remote.work.negotiate |= (1 << option.type);
  675.  
  676.         /* Add option response to the return list */
  677.         lcp_option (&reply_bp, &(lcp_p->remote.work), option.type, option.len, &data);
  678.     }
  679.  
  680.     /* Now check for any missing options which are desired */
  681.     if (fsm_p->retry_nak > 0 && (desired = lcp_p->remote.want.negotiate & ~lcp_p->remote.work.negotiate) != 0) {
  682.         switch (reply_result) {
  683.             case CONFIG_ACK:
  684.                 free_p (reply_bp);
  685.                 reply_bp = NULLBUF;
  686.                 reply_result = CONFIG_NAK;
  687.                 /* fallthru */
  688.             case CONFIG_NAK:
  689.                 lcp_makeoptions (&reply_bp, &(lcp_p->remote.want),
  690.                          desired);
  691.                 fsm_p->retry_nak--;
  692.                 break;
  693.             case CONFIG_REJ:
  694.             default:
  695.                 /* do nothing */
  696.                 break;
  697.         }
  698.     } else if (reply_result == CONFIG_NAK) {
  699.         /* if too many NAKs, reject instead */
  700.         if (fsm_p->retry_nak > 0)
  701.             fsm_p->retry_nak--;
  702.         else
  703.             reply_result = CONFIG_REJ;
  704.     }
  705.     /* Send ACK/NAK/REJ to remote host */
  706.     (void) fsm_send (fsm_p, uchar(reply_result), config->id, reply_bp);
  707.     free_p (data);
  708.     return (reply_result != CONFIG_ACK);
  709. }
  710.  
  711.  
  712.  
  713. /************************************************************************/
  714. /* Process configuration ACK sent by remote host */
  715. static int
  716. lcp_ack (struct fsm_s *fsm_p, struct config_hdr *config, struct mbuf *data)
  717. {
  718. struct mbuf *req_bp;
  719. int error = FALSE;
  720.  
  721.     PPP_DEBUG_ROUTINES ("lcp_ack()");
  722.  
  723.     /* ID field must match last request we sent */
  724.     if (config->id != fsm_p->lastid) {
  725.         PPP_DEBUG_CHECKS ("LCP ACK: wrong ID");
  726.         free_p (data);
  727.         return -1;
  728.     }
  729.     /* Get a copy of last request we sent */
  730.     req_bp = lcp_makereq (fsm_p);
  731.  
  732.     /* Overall buffer length should match */
  733.     if (config->len != len_p (req_bp)) {
  734.         PPP_DEBUG_CHECKS ("LCP ACK: buffer length mismatch");
  735.         error = TRUE;
  736.     } else {
  737.         register int req_char;
  738.         register int ack_char;
  739.  
  740.         /* Each byte should match */
  741.         while ((req_char = pullchar (&req_bp)) != -1) {
  742.             if ((ack_char = pullchar (&data)) == -1 || ack_char != req_char) {
  743.                 PPP_DEBUG_CHECKS ("LCP ACK: data mismatch");
  744.                 /*trace_log(PPPiface, "req=%02X, ack=%02X", req_char, ack_char);*/
  745.                 error = TRUE;
  746.                 break;
  747.             }
  748.         }
  749.     }
  750.     free_p (req_bp);
  751.     free_p (data);
  752.  
  753.     if (error)
  754.         return -1;
  755.  
  756.     PPP_DEBUG_CHECKS ("LCP ACK: valid");
  757.     return 0;
  758. }
  759.  
  760.  
  761.  
  762. /************************************************************************/
  763. /* Process configuration NAK sent by remote host */
  764. static int
  765. lcp_nak (struct fsm_s *fsm_p, struct config_hdr *config, struct mbuf *data)
  766. {
  767. struct lcp_s *lcp_p = fsm_p->pdv;
  768. struct lcp_side_s *local_p = &(lcp_p->local);
  769. int32 signed_length = config->len;
  770. struct option_hdr option;
  771. int last_option = 0;
  772. int result;
  773.  
  774.     PPP_DEBUG_ROUTINES ("lcp_nak()");
  775.  
  776.     /* ID field must match last request we sent */
  777.     if (config->id != fsm_p->lastid) {
  778.         PPP_DEBUG_CHECKS ("LCP NAK: wrong ID");
  779.         free_p (data);
  780.         return -1;
  781.     }
  782.     /* First, process in order.  Then, process extra "important" options */
  783.     while (signed_length > 0 && ntohopt (&option, &data) != -1) {
  784.         if ((signed_length -= option.len) < 0) {
  785.             PPP_DEBUG_CHECKS ("LCP NAK: bad header length");
  786.             free_p (data);
  787.             return -1;
  788.         }
  789.         if (option.type > LCP_OPTION_LIMIT)
  790.             PPP_DEBUG_CHECKS ("LCP NAK: option out of range");
  791.         else if (option.type < last_option || !(local_p->work.negotiate & (1 << option.type))) {
  792.             if (local_p->work.negotiate & (1 << option.type)) {
  793.                 PPP_DEBUG_CHECKS ("LCP NAK: option out of order");
  794.                 free_p (data);
  795.                 return -1;    /* was requested */
  796.             }
  797.             local_p->work.negotiate |= (1 << option.type);
  798.             last_option = LCP_OPTION_LIMIT + 1;
  799.         } else
  800.             last_option = option.type;
  801.  
  802.         if ((result = lcp_check (&data, lcp_p, local_p, &option, FALSE)) == -1) {
  803.             PPP_DEBUG_CHECKS ("LCP NAK: ran out of data");
  804.             free_p (data);
  805.             return -1;
  806.         }
  807.         /* update the negotiation status */
  808.         if (result == CONFIG_REJ && option.type <= LCP_OPTION_LIMIT)
  809.             local_p->work.negotiate &= ~(1 << option.type);        /*lint !e502 */
  810.     }
  811.     PPP_DEBUG_CHECKS ("LCP NAK: valid");
  812.     free_p (data);
  813.     return 0;
  814. }
  815.  
  816.  
  817.  
  818. /************************************************************************/
  819. /* Process configuration reject sent by remote host */
  820. static int
  821. lcp_reject (struct fsm_s *fsm_p, struct config_hdr *config, struct mbuf *data)
  822. {
  823. struct lcp_s *lcp_p = fsm_p->pdv;
  824. struct lcp_side_s *local_p = &(lcp_p->local);
  825. int32 signed_length = config->len;
  826. struct option_hdr option;
  827. int last_option = 0;
  828.  
  829.     PPP_DEBUG_ROUTINES ("lcp_reject()");
  830.  
  831.     /* ID field must match last request we sent */
  832.     if (config->id != fsm_p->lastid) {
  833.         PPP_DEBUG_CHECKS ("LCP REJ: wrong ID");
  834.         free_p (data);
  835.         return -1;
  836.     }
  837.     /* Process in order, checking for errors */
  838.     while (signed_length > 0 && ntohopt (&option, &data) != -1) {
  839.         register int k;
  840.  
  841.         if ((signed_length -= option.len) < 0) {
  842.             PPP_DEBUG_CHECKS ("LCP REJ: bad header length");
  843.             free_p (data);
  844.             return -1;
  845.         }
  846.         if (option.type > LCP_OPTION_LIMIT)
  847.             PPP_DEBUG_CHECKS ("LCP REJ: option out of range");
  848.         else if (option.type < last_option || !(local_p->work.negotiate & (1 << option.type))) {
  849.             PPP_DEBUG_CHECKS ("LCP REJ: option out of order");
  850.             free_p (data);
  851.             return -1;
  852.         }
  853.         for (k = option.len - OPTION_HDR_LEN; k-- > 0; ) {
  854.             if (pullchar (&data) == -1) {
  855.                 PPP_DEBUG_CHECKS ("LCP REJ: ran out of data");
  856.                 free_p (data);
  857.                 return -1;
  858.             }
  859.         }
  860.         last_option = option.type;
  861.  
  862.         if (option.type <= LCP_OPTION_LIMIT)
  863.             local_p->work.negotiate &= ~(1 << option.type);        /*lint !e502 */
  864.     }
  865.     PPP_DEBUG_CHECKS ("LCP REJ: valid");
  866.     free_p (data);
  867.     return 0;
  868. }
  869.  
  870.  
  871.  
  872. /************************************************************************/
  873. /*            I N I T I A L I Z A T I O N            */
  874. /************************************************************************/
  875.  
  876. /* Check for PPP Network-Layer Protocol Phase */
  877. void
  878. ppp_ready (struct ppp_s *ppp_p)
  879. {
  880.     if (!(ppp_p->flags & (PPP_AP_LOCAL | PPP_AP_REMOTE))) {
  881.         /* no pending authentication */
  882.         ppp_p->phase = pppREADY;
  883.  
  884.         ppp_p->upsince = secclock ();
  885.         fsm_start (&(ppp_p->fsm[IPcp]));
  886.     }
  887. }
  888.  
  889.  
  890.  
  891. /****************************************************************************/
  892. /* Reset configuration options before request */
  893. static void
  894. lcp_reset (struct fsm_s *fsm_p)
  895. {
  896. struct lcp_s *lcp_p = fsm_p->pdv;
  897.  
  898.     PPP_DEBUG_ROUTINES ("lcp_reset()");
  899.  
  900.     if (lcp_p->local.want.negotiate & LCP_N_MAGIC)
  901.         lcp_p->local.want.magic_number += (uint32) rdclock();
  902.  
  903.     ASSIGN (lcp_p->local.work, lcp_p->local.want);
  904.     lcp_p->local.will_negotiate |= lcp_p->local.want.negotiate;
  905.  
  906.     lcp_p->remote.work.negotiate = FALSE;
  907.     lcp_p->remote.will_negotiate |= lcp_p->remote.want.negotiate;
  908. }
  909.  
  910.  
  911.  
  912. /************************************************************************/
  913. /* Prepare to begin configuration exchange */
  914. static void
  915. lcp_starting (struct fsm_s *fsm_p)
  916. {
  917.     PPP_DEBUG_ROUTINES ("lcp_starting()");
  918.  
  919.     fsm_p->ppp_p->phase = pppLCP;
  920. }
  921.  
  922.  
  923.  
  924. /************************************************************************/
  925. /* After termination */
  926. static void
  927. lcp_stopping (struct fsm_s *fsm_p)
  928. {
  929. struct iface *ifp = fsm_p->ppp_p->iface;
  930.  
  931.     PPP_DEBUG_ROUTINES ("lcp_stopping()");
  932.  
  933.     /* Tell the dialer to shut down */
  934.     if (ifp->supv != NULLPROC)
  935.         alert (ifp->supv, EABORT);
  936.  
  937.     /* Now, tell the device to go down.
  938.      * In turn, it should tell our IO status
  939.      * when it has gone down.
  940.      */
  941.     (void) ifp->ioctl (ifp, PARAM_DOWN, TRUE, 0L);
  942. }
  943.  
  944.  
  945.  
  946. /************************************************************************/
  947. /* Close higher levels in preparation for link shutdown */
  948. static void
  949. lcp_closing (struct fsm_s *fsm_p)
  950. {
  951. struct ppp_s *ppp_p = fsm_p->ppp_p;
  952.  
  953.     ppp_p->phase = pppTERMINATE;
  954.  
  955.     fsm_down (&(ppp_p->fsm[IPcp]));
  956.     pap_down (&(ppp_p->fsm[Pap]));
  957. }
  958.  
  959.  
  960.  
  961. /************************************************************************/
  962. /* configuration negotiation complete */
  963. static void
  964. lcp_opening (struct fsm_s *fsm_p)
  965. {
  966. struct lcp_s *lcp_p = fsm_p->pdv;
  967. struct iface *ifp = fsm_p->ppp_p->iface;
  968.  
  969.     if (ifp->mtu != lcp_p->remote.work.mru) {
  970.         /* Set new Max Transmission Unit for outgoing packets */
  971.         ifp->mtu = lcp_p->remote.work.mru;
  972.         if (PPPtrace > 1)
  973.             trace_log (PPPiface, "    Set new MTU for outgoing packets: %d", ifp->mtu);
  974.     }
  975.     /* check for authentication */
  976.     fsm_p->ppp_p->phase = pppAP;
  977.     fsm_p->ppp_p->flags &= ~(PPP_AP_LOCAL | PPP_AP_REMOTE);
  978.     free (fsm_p->ppp_p->peername);
  979.     fsm_p->ppp_p->peername = NULLCHAR;
  980.  
  981.     if (lcp_p->local.work.negotiate & LCP_N_AUTHENT) {
  982.         switch (lcp_p->local.work.authentication) {
  983.             case PPP_PAP_PROTOCOL:
  984.                 (void) pap_local (fsm_p->ppp_p);
  985.                 break;
  986.             default:
  987.                 break;
  988.         }
  989.     }
  990.     if (lcp_p->remote.work.negotiate & LCP_N_AUTHENT) {
  991.         switch (lcp_p->remote.work.authentication) {
  992.             case PPP_PAP_PROTOCOL:
  993.                 (void) pap_remote (fsm_p->ppp_p);
  994.                 break;
  995.             default:
  996.                 break;
  997.         }
  998.     }
  999.     /* re-check for authentication */
  1000.     ppp_ready (fsm_p->ppp_p);
  1001. }
  1002.  
  1003.  
  1004.  
  1005. /************************************************************************/
  1006. static void
  1007. lcp_free (struct fsm_s *fsm_p OPTIONAL)
  1008. {
  1009.     /* nothing to do */
  1010. }
  1011.  
  1012.  
  1013.  
  1014. /* Initialize configuration structure */
  1015. void
  1016. lcp_init (struct ppp_s *ppp_p)
  1017. {
  1018. struct fsm_s *fsm_p = &(ppp_p->fsm[Lcp]);
  1019. struct lcp_s *lcp_p;
  1020.  
  1021.     PPPtrace = ppp_p->trace;
  1022.     PPPiface = ppp_p->iface;
  1023.  
  1024.     PPP_DEBUG_ROUTINES ("lcp_init()");
  1025.  
  1026.     fsm_p->ppp_p = ppp_p;
  1027.     fsm_p->pdc = &lcp_constants;
  1028.     fsm_p->pdv = lcp_p = callocw (1, sizeof (struct lcp_s));
  1029.  
  1030.     /* Set option parameters to first request defaults */
  1031.     ASSIGN (lcp_p->local.want, lcp_default);
  1032.     lcp_p->local.will_negotiate = lcp_negotiate;
  1033.  
  1034.     ASSIGN (lcp_p->remote.want, lcp_default);
  1035.     ASSIGN (lcp_p->remote.work, lcp_default);
  1036.     lcp_p->remote.will_negotiate = lcp_negotiate;
  1037.  
  1038.     fsm_init (fsm_p);
  1039. }
  1040.  
  1041. #endif /* PPP */
  1042.